home *** CD-ROM | disk | FTP | other *** search
- /*
- FNS_C - QL-Kermit protocol functions
-
- Based on ckcfns.c, (C) Columbia University
- */
-
-
- /* Include files */
-
- #include "ram1_ker_h" /* Kermit definitions */
-
-
- /* External variables */
-
- extern int slen; /* Maximum send packet size */
- extern int rlen; /* Maximum receive packet size */
- extern int tslen; /* Send packet size in use */
- extern int stmo; /* Timeout remote is to use */
- extern int rtmo; /* Timeout we will use */
- extern int n; /* Packet number */
- extern int ttyfd; /* FD of TTY for I/O, 0 if remote */
- extern int ttychid; /* Channel ID for ttyfd */
- extern int tvalue; /* Current timeout value */
- extern int debug; /* Level of debugging output */
- extern int parity; /* Current parity setting */
- extern int npad; /* Amount of padding remote needs */
- extern int tnpad; /* Padding count in use */
- extern int xfertyp; /* File transfer mode */
-
- extern long filein; /* File bytes received */
- extern long fileout; /* File bytes sent */
- extern long totin; /* Total bytes received */
- extern long totout; /* Total bytes sent */
-
- extern bool timer; /* Timer enabled */
- extern bool cxseen; /* File interruption flag */
- extern bool czseen; /* Group interruption flag */
- extern bool toscr; /* Screen data flag */
- extern bool ebqflg; /* 8-bit quoting being done */
-
- extern char ssop; /* SOP remote needs */
- extern char rsop; /* SOP I need */
- extern char seol; /* EOL for sending packets */
- extern char reol; /* EOL for receiving packets */
- extern char tseol; /* Sending EOL in use */
- extern char quote; /* Sending control quote */
- extern char pebq; /* 8-bit quote prefix */
- extern char tquote; /* Receiving control quote */
- extern char ebq; /* 8-bit quote in use */
-
- extern unsigned char padch; /* Pad character remote needs */
- extern unsigned char tpadc; /* Pad character in use */
-
- extern char *ttyname; /* Name of TTY for transfer */
-
- extern int fp; /* Local file for data transfer */
-
- extern int _oserr; /* QDOS error code */
- extern int oserr; /* Copy of above */
-
- extern bool warn8; /* Lost 8th bit warning given */
-
- extern int state; /* Current switcher state */
-
-
- /* External functions */
-
- extern bool chkquote(); /* Check for valid quote character */
- extern bool tfput(); /* Put a byte to transfer file */
- extern int tfget(); /* Get a byte from transfer file */
-
-
- /* Local variables */
-
- static int length; /* Length of last packet read */
-
-
- /* TINIT - Initialise transaction */
-
- tinit()
- {
- tseol = seol; /* Initialise sending EOL, */
- tslen = slen; /* packet length */
- tvalue = 50*rtmo; /* and timeout */
- czseen = FALSE; /* Clear interrupt flags */
- cxseen = FALSE;
- tnpad = npad; /* Initialise padding */
- tpadc = padch;
- tquote = quote; /* and quote characters */
- ebq = 0;
- ebqflg = FALSE; /* Reset 8-bit quote flag */
- totin = totout = 0; /* Clear character counts */
- }
-
-
- /* SPACK - Send a packet */
-
- spack(type,num,len,data)
- char type;
- int num,len;
- char *data;
- {
- int i; /* Character loop counter */
- char chksum; /* Checksum */
- char buffer[110]; /* Packet buffer */
- char *bufp; /* Buffer pointer */
-
- if (debfull) /* Display outgoing packet? */
- {
- if (data!=NULL) data[len] = '\0'; /* Null-terminate data for printing */
- printf("spack: type=%c, num=%d, len=%d\n",type,num,len);
- if (data!=NULL) printf(" data=\"%s\"\n",data);
- }
-
- bufp = buffer; /* Set up buffer pointer */
-
- *bufp++ = ssop; /* Packet marker (SOH) */
-
- chksum = *bufp++ = tochar(len+3); /* Character count */
-
- *bufp++ = tochar(num); /* Packet number */
- chksum += tochar(num); /* Update checksum */
-
- *bufp++ = type; /* Packet type */
- chksum += type; /* Update checksum */
-
- for (i=0; i<len; i++) /* Loop for all data characters */
- {
- *bufp++ = data[i]; /* Put a character */
- chksum += data[i]; /* Update checksum */
- }
-
- chksum = (((chksum&0300)>>6)+chksum)&077; /* Compute final checksum */
- *bufp++ = tochar(chksum); /* Put it in the packet */
- *bufp = tseol; /* Add packet line terminator */
- write(ttyfd,buffer,bufp-buffer+1); /* and send the packet */
-
- for (i = 0; i<tnpad; i++)
- write(ttyfd,&tpadc,1); /* Put out any padding needed */
- }
-
-
- /* RPACK - Read a packet */
-
- int rpack(len,num,data)
- int *len,*num;
- char *data;
- {
- int i; /* Loop counter */
- bool done; /* Loop exit */
- char type; /* Packet type */
- int t; /* Current input character */
- char ccsum; /* Our (computed) checksum */
- char rcsum; /* Checksum received from host */
-
- done = FALSE; /* Start to look for a packet */
- do
- {
- if ((t = tread())<0) return(t); /* Error */
- } while (t!=rsop); /* Look for start of packet */
-
- while (!done) /* Got SOP, loop to get packet */
- {
- if ((t = tread())<0) return(t); /* Error */
- if (t==rsop) continue; /* Aborted packet */
- ccsum = t; /* Start the checksum */
- *len = unchar(t)-3; /* Character count */
-
- if ((t = tread())<0) return(t); /* Error */
- if (t==rsop) continue; /* Aborted packet */
- ccsum += t; /* Update checksum */
- *num = unchar(t); /* Packet number */
-
- if ((t = tread())<0) return(t); /* Error */
- if (t==rsop) continue; /* Aborted packet */
- ccsum += t; /* Update checksum */
- type = t; /* Packet type */
-
- for (i=0; i<*len; i++) /* Loop for data */
- {
- if ((t = tread())<0) return(t); /* Error */
- if (t==rsop) goto xx; /* Aborted packet */
- ccsum += t; /* Update checksum */
- data[i] = t; /* Put it in the data buffer */
- }
- data[*len] = '\0'; /* Mark the end of the data */
-
- if ((t = tread())<0) return(t); /* Error */
- xx: if (t==rsop) continue; /* Aborted packet */
- rcsum = unchar(t); /* Convert checksum to numeric */
-
- done = TRUE; /* Got checksum, done */
- length = *len; /* Save length for rpar() */
- }
-
- if (debfull) /* Display incoming packet */
- {
- if (data!=NULL) data[*len] = '\0'; /* Null-terminate data for printing */
- printf("rpack type: %c, num: %d, len: %d\n",type,*num,*len);
- if (data!=NULL) printf(" data: \"%s\"\n",data);
- }
-
- /* Fold in bits 7,8 to */
- ccsum = (((ccsum&0300)>>6)+ccsum)&077; /* compute final checksum */
-
- if (ccsum!=rcsum) /* Checksum correct? */
- {
- if (debon) printf("Received bad checksum\n");
- return(BAD);
- }
- return((int) type); /* All OK, return packet type */
- }
-
-
- /* BUFILL - Get a bufferful of data from the file that's being sent and
- encode it for transmission.
- */
-
- int bufill(buff)
- char buff[];
- {
- int i; /* Loop index */
- char t; /* Character read from file */
- int tt; /* For testing EOF */
- int a7,b8; /* Split-up versions of above */
-
- i = 0; /* Set up data buffer pointer */
- while ((tt = tfget())!=EOF) /* Get the next character */
- {
- fileout++; /* Count it */
-
- t = (char) tt;
- a7 = t&0177; /* Get lower 7 bits */
- b8 = t&0200; /* and 8th bit */
-
- if (a7!=t && !warn8 && !ebqflg && parity!=PYNONE)
- { /* Check for data loss */
- printf("Warning: 8th bits lost\n");
- warn8 = TRUE;
- }
-
- if (ebqflg && b8!=0) /* EBQ required? */
- {
- buff[i++] = ebq; /* Yes, put out prefix */
- t = a7; /* and work on 7-bit character */
- }
-
- if (a7<SP || a7==DEL) /* Control quote required? */
- {
- buff[i++] = quote; /* Yes, output prefix */
- if (t==LF && xfertyp==FTASC) /* EOL in ASCII mode */
- {
- buff[i++] = 'M'; /* Standard Kermit EOL sequence */
- buff[i++] = quote;
- t = 'J';
- }
- else t = ctl(t); /* Uncontrollify */
- }
-
- if (a7==quote || (a7==ebq && ebqflg))
- {
- buff[i++] = quote; /* Quote control prefix or EBQ */
- }
-
- buff[i++] = t; /* Finally output the character */
-
- if (i>=tslen-9) return(i); /* Conservative length check */
- }
- if (i==0) return(EOF); /* Here only on EOF */
- return(i); /* Handle partial buffer */
- }
-
-
- /* BUFEMP - Put data from an incoming packet into a file */
-
- bool bufemp(buff,len)
- char buff[];
- int len;
- {
- int i; /* Counter */
- char t; /* Character holder */
- int a,a7,b8; /* Component parts of above */
- char fbuf[MAXPACK]; /* File data buffer */
- int fbufp = 0; /* Index into above */
-
- for (i=0; i<len; i++) /* Loop through the data */
- {
- a = buff[i]; /* Get character */
- b8 = 0; /* Clear high bit flag */
-
- if (ebqflg && a==ebq) /* An 8-bit prefixed sequence? */
- {
- b8 = 0200; /* Set 8th bit for later */
- a = buff[++i]; /* and get prefixed character */
- }
-
- if (a==tquote) /* Control quote? */
- {
- a = buff[++i]; /* Yes, get what it prefixes */
- a7 = a&0177; /* Split off lower 7 bits */
- if ((a7>=0100 && a7<=0137) || a7=='?')
- a = ctl(a); /* Uncontrollify */
- }
-
- t = (char) a | b8; /* Add in 8th bit */
-
- if (toscr && t!=CR) putch(t); /* Screen output */
- else if (!(t==CR && xfertyp==FTASC)) /* File output */
- fbuf[fbufp++] = t;
- filein++; /* Count the character */
- }
-
- if (!toscr) /* File output */
- {
- if (write(fp,fbuf,fbufp)!=fbufp) /* Write to file */
- {
- oserr = _oserr; /* Save error code */
- return(FALSE);
- }
- }
- else if (n==1) putch('\n'); /* Set screen for DO results */
- return(TRUE);
- }
-
-
- /* SPAR - Fill the data array with my Send-Init parameters */
-
- int spar(data)
- char data[];
- {
- data[0] = tochar(rlen); /* Biggest packet I can receive */
- data[1] = tochar(stmo); /* When I want to be timed out */
- data[2] = tochar(0); /* How much padding I need */
- data[3] = ctl('\0'); /* Padding character I need */
- data[4] = tochar(reol); /* End-Of-Line character I need */
- data[5] = quote; /* Quote character I send */
-
- if (parity!=PYNONE || ebqflg) /* 8-bit quoting required? */
- {
- data[6] = pebq; /* Ask for what we have SET */
- if (chkquote(ebq) || ebq=='Y')
- ebqflg = TRUE; /* If valid reply, set flag */
- }
- else data[6] = 'Y'; /* Not required, just say we're willing */
-
- data[7] = '1'; /* Checksum type 1 */
- data[8] = ' '; /* No repeat count capability */
-
- return(9); /* Return the length */
- }
-
-
- /* RPAR - Get and analyse the remote's Send-Init parameters */
-
- #define IFP if (length-->0) /* If field is present */
-
- rpar(data)
- char data[];
- {
- IFP tslen = min(unchar(data[0]),tslen); /* Maximum send packet size */
- IFP tvalue = max(50*unchar(data[1]),tvalue); /* When I should time out */
- IFP tnpad = max(unchar(data[2]),tnpad); /* Padding required */
- IFP tpadc = ctl(data[3]); /* Padding character */
- IFP tseol = unchar(data[4]); /* EOL character I must send */
- IFP tquote = data[5]; /* Incoming data quote character */
-
- IFP
- {
- ebq = data[6]; /* EBQ remote will use */
-
- if (chkquote(ebq)) ebqflg = TRUE; /* If acceptable, we will too */
- else if ((parity!=PYNONE || ebqflg) && ebq=='Y')
- { /* We need it, remote says OK */
- ebqflg = TRUE;
- ebq = pebq; /* Use what we have SET */
- }
- else if (ebq=='N')
- {
- ebqflg = FALSE; /* We need it, remote can't do */
- }
- else ebqflg = FALSE; /* Some other reply */
- }
- else ebqflg = FALSE; /* No reply */
-
- if (tseol==0) tseol = '\r'; /* Check and set defaults */
- if (tquote==0) tquote = quote;
- if (tslen<10) tslen = 10;
-
- if (debon)
- {
- printf("rpar: timeout=%d, length=%d, EOL=%d\n",tvalue/50,tslen,tseol);
- printf(" npad=%d, padchar=0%o, quote=%c\n",tnpad,tpadc,tquote);
- printf(" 8-bit quoting %s",(ebqflg ? "yes" : "no"));
- if (ebqflg) printf(", with %c",ebq);
- printf("\n");
- }
- }
-
-
- /* ACK - Send an acknowledgement with no data */
-
- ack()
- {
- spack('Y',n,0,0);
- }
-
-
- /* ACK1 - Send an acknowledgement with 1 character of data */
-
- ack1(s)
- char *s;
- {
- spack('Y',n,1,s);
- }
-
-
- /* ACKN - Acknowledge a specific packet number */
-
- ackn(num)
- int num;
- {
- spack('Y',num,0,0);
- }
-
-
- /* NAK - Send a negative acknowledegement */
-
- nak()
- {
- spack('N',n,0,0);
- }
-